#nullable enable
namespace Application.Service.Auth;

/// <summary>
/// 认证服务类
/// <para>功能：提供用户认证、登录、注销等核心认证功能</para>
/// <list type="bullet">
/// <item><description>验证用户身份信息</description></item>
/// <item><description>管理用户登录状态</description></item>
/// <item><description>处理会话创建和销毁</description></item>
/// <item><description>提供强制注销功能</description></item>
/// </list>
/// </summary>
public class AuthService: ISingleton
{
    public bool IsAuthenticated { get; private set; }
    public string Username { get; private set; } = string.Empty;
    public string CurrentSessionId { get; private set; } = string.Empty;
    
    public IUserService _userService;
    private readonly SessionManagerService _sessionManager;
    
    public AuthService(IUserService userService, SessionManagerService sessionManager)
    {
        _userService = userService;
        _sessionManager = sessionManager;
    }
    
    public event Action? OnAuthenticationStateChanged;
    
    /// <summary>
    /// 验证指定用户名是否存在于系统中
    /// </summary>
    /// <param name="username">用户名</param>
    /// <returns>
    /// 返回用户存在状态和错误信息
    /// <para>Success: 用户是否存在</para>
    /// <para>ErrorMessage: 错误信息（如果用户不存在）</para>
    /// </returns>
    public async Task<(bool Success, string ErrorMessage)> CheckUserAsync(string username)
    {
        var user = await _userService.GetAsync(username);
        if (user == null)
        {
            Log.Error("无此用户");
            return (false, "无此用户");
        }
        return (true, string.Empty);
    }

    /// <summary>
    /// 验证用户凭据并创建登录会话(用户登录)
    /// </summary>
    /// <param name="username">用户名</param>
    /// <param name="password">密码(加盐后的MD5哈希值)</param>
    /// <returns> 
    /// 返回登录状态、用户信息和会话信息
    /// <para>Success: 登录是否成功</para>
    /// <para>ErrorMessage: 错误信息（如果登录失败）</para>
    /// <para>UserId: 用户ID（登录成功时返回）</para>
    /// <para>DisplayName: 显示名称（登录成功时返回）</para>
    /// </returns>
    public async Task<(bool Success, string ErrorMessage, int UserId, string DisplayName)> LoginAsync(string username, string password)
    {
        var user = await _userService.GetAsync(username);

        if (user == null)
        {
            Log.Error("无此用户");
            return (false, "无此用户", -1, "");
        }

        if (!MD5Encryption.Compare(password, user.PasswordHash,true,false))
        {
            Log.Error("密码错误");
            return (false, "密码错误", -1, "");
        }

        // 检查用户是否已在其他客户端登录
        if (_sessionManager.IsUserLoggedIn(user.Id))
        {
            Log.Warning($"用户 {username} 已在其他客户端登录，拒绝新登录");
            return (false, "用户已在其他客户端登录", -1, "");
        }

        // 生成新的会话ID
        var sessionId = GenerateSessionId();
        
        // 创建会话
        if (!_sessionManager.CreateSession(user.Id, sessionId))
        {
            Log.Error($"用户 {username} 创建会话失败");
            return (false, "登录失败，请稍后重试", -1, "");
        }

        IsAuthenticated = true;
        Username = username;
        CurrentSessionId = sessionId;
        OnAuthenticationStateChanged?.Invoke();
        
        Log.Information($"用户 {username} 登录成功，会话ID: {sessionId}");
        return (true, string.Empty, user.Id, user.DisplayName ?? "");
    }
    
    /// <summary>
    /// 终止当前用户的登录会话，清除用户登录状态和会话信息(用户注销)
    /// </summary>
    public void Logout()
    {
        // 移除会话
        if (!string.IsNullOrEmpty(CurrentSessionId))
        {
            _sessionManager.RemoveSession(CurrentSessionId);
            Log.Information($"用户 {Username} 注销，会话ID: {CurrentSessionId}");
        }
        
        IsAuthenticated = false;
        Username = string.Empty;
        CurrentSessionId = string.Empty;
        OnAuthenticationStateChanged?.Invoke();
    }
    
    /// <summary>
    /// 强制注销指定用户（踢出登录）
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <returns>是否成功强制终止用户会话并返回操作结果</returns>
    public bool ForceLogout(int userId)
    {
        var result = _sessionManager.ForceLogout(userId);
        if (result)
        {
            Log.Information($"强制注销用户ID: {userId}");
            
            // 如果强制注销的是当前用户，需要更新当前状态
            if (IsAuthenticated && _userService.GetAsync(Username).Result?.Id == userId)
            {
                IsAuthenticated = false;
                Username = string.Empty;
                CurrentSessionId = string.Empty;
                OnAuthenticationStateChanged?.Invoke();
            }
        }
        return result;
    }
    
    /// <summary>
    /// 生成基于时间戳的唯一会话标识符ID
    /// </summary>
    /// <returns>返回唯一的、基于时间的会话ID</returns>
    private string GenerateSessionId()
    {
        
        DateTimeOffset customTime = new(DateTimeOffset.Now.Year, DateTimeOffset.Now.Month, DateTimeOffset.Now.Day, DateTimeOffset.Now.Hour, DateTimeOffset.Now.Minute, DateTimeOffset.Now.Second, TimeSpan.Zero);
        return Guid.CreateVersion7(customTime).ToString("N") ;
    }
}